﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using NLite.Collections;
using NLite.Reflection;
using NLite.Internal;
namespace NLite.Messaging.Internal
{
    [Serializable]
    [DebuggerTypeProxy(typeof(DebuggerEnumerableView<>))]
    class MessageRepository : MarshalDisposable, IMessageRepository
    {
        private IMap<Key, ISubject> Table;
        private ISubjectBuilder Builder;
        private IDelegateInvoker DelegateInvoker;

        public IMessageListenerManager ListnerManager { get; private set; }

        
        public MessageRepository()
        {
            Table = new ConcurrentMap<Key, ISubject>();
            Builder = new SubjectBuilder();
            ListnerManager = new MessageListnerManager();
            DelegateInvoker = new NLite.Messaging.Internal.DelegateInvoker();
        }
       
        public int Count
        {
            get { return Table.Count; }
        }

  
        public ISubject this[string topic, Type type]
        {
            get
            {
                var key = string.IsNullOrEmpty(topic) ? Key.Make(type):Key.Make(type, topic);
                ISubject subject = null;

                if (Table.TryGetValue(key, out subject))
                    return subject;

                subject = Builder.Build(key.ToString());
                subject.Subscriber.ListnerManager = ListnerManager;
                subject.Executor.ListnerManager = ListnerManager;
                subject.Executor.DelegateInvoker = DelegateInvoker;
                Table[key] = subject;

                return subject;
            }
        }

      

        public void Remove(string topic, Type type)
        {
            var key = Key.Make(type, topic);
            if (Table.ContainsKey(key))
            {
                var subject = Table[key];
                Table.Remove(key);
                subject.Dispose();
            }
        }

        public void Clear()
        {
            var tmpItems = Table.Values.ToArray();
            

            if (tmpItems != null && tmpItems.Length > 0)
                tmpItems.ForEach(item => item.Dispose());

            Table.Clear();
        }


        protected override void Dispose(bool disposing)
        {
            if (disposing)
                Clear();
        }

      
       
    }
}
